/**
 * 内存常见问题 https://www.bilibili.com/video/BV1vs411n7TH?p=100
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void fun08(int *p);
void fun09(int **p);

int main() {
    //1.如果把这个字符数组作为字符串, 那么下标越界了(非'\0'结尾)
    char ch[11] = "hello world";

    //2.strcpy(), 0没有copy进去
    int size = sizeof(char) * 11;
    char *p1 = (char*) malloc(size);
    strcpy(p1, "hello world");   //字符串常量以'\0' 结尾, 0没有copy进去, free()的时候会报错(我的没报错)
    printf("p1 = %s\n", p1);
    free(p1);

    //3.malloc(0), 赋值int, free()报错.(我的没报错)
    int *p2 = (int*) malloc(0);
    printf("p2 = %p\n", p2);        //001D11E0
    *p2 = 100;
    printf("p2 = %d\n", *p2);       //100
    free(p2);

    //4.重复释放堆空间, 报错.(我的没报错)
    int *p3 = (int*) malloc(size);
    free(p3);               //正确释放
//    free(p3);             //野指针
    p3 = NULL;              //应该置空

    //5.指针位置已改变, 释放报错.(我的没报错)
    int *p4 = (int*) malloc(size);
    int * temp = p4;        //应该操作temp
    for (int i = 0; i < 11; ++i) {
        *p4 = i;
        p4++;
    }
    p4 -= 11;             //应操作temp / p4位置还原, 否则报错
    free(p4);
    printf("5.指针位置已改变, 释放报错.\n");

    //6.空指针要正确初始化
    int *p5 = NULL;
    //值传递
//    fun08(p5);             //应该写成: &p5, 否则p5=NULL, 赋值会报错
    //地址传递
    fun09(&p5);
    for (int i = 0; i < 10; ++i) {
        p5[i] = i;
    }
    free(p5);
    p5 = NULL;

    return EXIT_SUCCESS;
}
void fun08(int *p) {       //应该写成: int **p
    p = (int*) malloc(40); //应该写成: *p = ...
}
void fun09(int **p) {
    *p = (int*) malloc(40);
}